package com.woniuxy.commons.filter;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.commons.exception.LoginPhoneException;
import com.woniuxy.controller.dto.AccountDto;
import com.woniuxy.controller.form.PhoneCodeAuthenticationToken;
import com.woniuxy.dao.UriInfoDao;
import com.woniuxy.dao.model.Account;
import com.woniuxy.service.AccountService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


public class PhoneCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "phone";

    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "code";

    private static final AntPathRequestMatcher
            DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/phoneLogin",
            "POST");

    private String phoneParameter = SPRING_SECURITY_FORM_USERNAME_KEY;

    private String codeParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;

    private boolean postOnly = true;

    private AccountService accountInfoService;

    private UriInfoDao uriInfoDao;

    private StringRedisTemplate srt;

    public PhoneCodeAuthenticationFilter() {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
    }

    public PhoneCodeAuthenticationFilter(AccountService accountInfoService,
                                         UriInfoDao uriInfoDao,
                                         StringRedisTemplate srt) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        this.accountInfoService = accountInfoService;
        this.uriInfoDao = uriInfoDao;
        this.srt = srt;
    }

    public PhoneCodeAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String phone = obtainPhone(request);
        phone = (phone != null) ? phone : "";
        phone = phone.trim();
        String code = obtainCode(request);
        code = (code != null) ? code : "";
        code = code.trim();
        //通过电话查询用户
        Account account =
                accountInfoService.getOne(
                        new QueryWrapper<Account>().eq("account_phone", phone));

        //判断账号是否是激活状态
        if (account.getState()==0)throw new LoginPhoneException(1004,"账号未激活或者被禁用");

        if(account != null) {

            String phoneCode = srt.opsForValue().get("login:phone:code:" + phone);
            System.out.println(phoneCode);
            if (phoneCode == null || !(phoneCode.equals(code))) throw new LoginPhoneException(1003,"验证码有误，或已失效");
            AccountDto lud = new AccountDto();
            lud.setId(account.getId());
            lud.setAccountPhone(account.getAccountPhone());
            lud.setAccount(account.getAccount());
            lud.setAccountName(account.getAccountName());
            lud.setAccountEmail(account.getAccountEmail());
            lud.setState(account.getState());
            System.out.println(account.getId());
            List<String> uris = uriInfoDao.loadUriValue(account.getId());
            System.out.println(uris+"ssssssss");
            if (uris != null && uris.size()>0){

                lud.setRoles(uris);
            }
            PhoneCodeAuthenticationToken token =            //配置权限方式一
                    new PhoneCodeAuthenticationToken(lud,null);
            setDetails(request, token);
            return token;
        }
        throw new LoginPhoneException(5004,"该账号不存在");
    }


    @Nullable
    protected String obtainCode(HttpServletRequest request) {
        return request.getParameter(this.codeParameter);
    }

    @Nullable
    protected String obtainPhone(HttpServletRequest request) {
        return request.getParameter(this.phoneParameter);
    }

    protected void setDetails(HttpServletRequest request,
                              PhoneCodeAuthenticationToken authRequest) {
        authRequest.setDetails(
                this.authenticationDetailsSource.buildDetails(request));
    }


    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getPhoneParameter() {
        return this.phoneParameter;
    }

    public final String getCodeParameter() {
        return this.codeParameter;
    }
}
